package com.faner4cloud.redisson.configuration;

import org.redisson.client.handler.PingConnectionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.logging.LogLevel;
import org.springframework.context.ApplicationListener;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class RedisLoggingApplicationListener implements ApplicationListener<ApplicationPreparedEvent> {

    private static final Logger LOGGER = LoggerFactory.getLogger(RedisLoggingApplicationListener.class);

    @Override
    public void onApplicationEvent(ApplicationPreparedEvent applicationPreparedEvent) {
        // 关闭ping connect异常，减少无意义ping异常报警
        Logger logger = LoggerFactory.getLogger(PingConnectionHandler.class);
        changeLoggingLevel(logger, LogLevel.OFF.name());
    }

    private void changeLoggingLevel(Logger logger, String level) {
        try {
            Class<?> c = Class.forName("ch.qos.logback.classic.Level");
            Method method = logger.getClass().getMethod("setLevel", c);
            Object value = c.getDeclaredField(level).get(null);
            method.invoke(logger, value);
        } catch (Exception ex1) {
            LOGGER.warn("Got error when changing log level for logback(clz={}, level={}, ex={}, msg={})", logger.getName(), level, ex1.getClass().getName(), ex1.getMessage());
            Field extLoggerField = null;
            boolean isAccessible = false;
            try {
                extLoggerField = logger.getClass().getDeclaredField("logger");
                isAccessible = extLoggerField.isAccessible();
                extLoggerField.setAccessible(true);

                Class<?> c = Class.forName("org.apache.logging.log4j.Level");
                Object value = c.getDeclaredField(level).get(null);
                Object loggerObj = extLoggerField.get(logger);
                Method method = loggerObj.getClass().getMethod("setLevel", c);
                method.invoke(loggerObj, value);
            } catch (Exception ex2) {
                LOGGER.warn("Got error when changing log level for log4j2(clz={}, level={}, ex={}, msg={})", logger.getName(), level, ex1.getClass().getName(), ex1.getMessage());
            } finally {
                if (extLoggerField != null) {
                    extLoggerField.setAccessible(isAccessible);
                }
            }
        }
    }
}
